package com.zhang.backend.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * A holder to access the Spring ApplicationContext from non-Spring managed classes.
 * <p>
 * Use this class with caution. It is generally better to use Dependency Injection (@Autowired)
 * whenever possible, as it makes dependencies explicit and your code easier to test.
 */
@Component
public class SpringContextHolder implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextHolder.applicationContext = applicationContext;
    }

    /**
     * Retrieves the singleton ApplicationContext.
     *
     * @return The ApplicationContext instance.
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * Retrieves a Spring-managed bean by its class type.
     *
     * @param requiredType The class of the bean to retrieve.
     * @param <T>          The generic type of the bean.
     * @return The requested bean instance.
     */
    public static <T> T getBean(Class<T> requiredType) {
        assertApplicationContext();
        return applicationContext.getBean(requiredType);
    }

    /**
     * Retrieves a Spring-managed bean by its name.
     *
     * @param name The name of the bean.
     * @return The bean instance as an Object.
     */
    public static Object getBean(String name) {
        assertApplicationContext();
        return applicationContext.getBean(name);
    }

    private static void assertApplicationContext() {
        if (applicationContext == null) {
            throw new IllegalStateException("ApplicationContext not initialized. " +
                    "Ensure SpringContextHolder is registered as a Spring bean.");
        }
    }
}